package org.iamd.service;

import java.util.List;

import org.quartz.SchedulerException;
import org.quartz.impl.StdSchedulerFactory;

/**
 * Scheduler менажиращ фонови процеси.
 * 
 * @author И. Атанасов
 */
public class ServiceScheduler {

	/** Единствена инстанция */
	private static ServiceScheduler instance;

	/**
	 * @return единствената инстанция
	 * 
	 * @throws SchedulerException
	 *             при неуспешно инстанциране
	 */
	public static ServiceScheduler getScheduler() throws SchedulerException {
		if (instance == null) {
			instance = new ServiceScheduler();
		}
		return instance;
	}

	/**
	 * Стартиране на мениджъра на фонови процеси.
	 * 
	 * @throws SchedulerException
	 *             при неуспешен старт
	 */
	private ServiceScheduler() throws SchedulerException {
		StdSchedulerFactory.getDefaultScheduler().start();
	}

	/**
	 * Маркира сервиз за стартиране. Начина, периода през който се повтаря,
	 * както и забавянето му след маркиране за стариране се определят по данните
	 * в подадения сервиз.
	 * 
	 * @param service
	 *            сервизът, който трябва да бъде стартиран
	 * 
	 * @throws SchedulerException
	 *             при неуспешно стартиране
	 */
	public void schedule(ServiceWrapper service) throws SchedulerException {
		StdSchedulerFactory.getDefaultScheduler().scheduleJob(service.getDetail(),
				service.getTrigger());
	}

	/**
	 * Стартира подадените сервизи.
	 * 
	 * @param services
	 *            списък сервизи
	 * 
	 * @throws SchedulerException
	 *             при неуспешно стартиране на някой от процесите
	 * 
	 * @see ServiceScheduler#schedule(ServiceWrapper)
	 */
	public void startServices(List<ServiceWrapper> services) throws SchedulerException {
		SchedulerException firstEx = null;
		for (ServiceWrapper s : services) {
			try {
				schedule(s);
			} catch (SchedulerException e) {
				if (firstEx == null) {
					firstEx = e;
				}
			}
		}
		if (firstEx != null) {
			throw firstEx;
		}
	}

	/**
	 * Спира подадените сервизи.
	 * 
	 * @param services
	 *            списък сервизи
	 * 
	 * @throws SchedulerException
	 *             при неуспешно спиране на някой от процесите
	 * 
	 * @see ServiceScheduler#unschedule(ServiceWrapper)
	 */
	public void stopServices(List<ServiceWrapper> services) throws SchedulerException {
		SchedulerException firstEx = null;
		for (ServiceWrapper s : services) {
			try {
				unschedule(s);
			} catch (SchedulerException e) {
				if (firstEx == null) {
					firstEx = e;
				}
			}
		}
		if (firstEx != null) {
			throw firstEx;
		}
	}

	/**
	 * Маркира сервиз за спиране.
	 * 
	 * @param service
	 *            сервизът, който трябва да бъде спрян
	 * 
	 * @throws SchedulerException
	 *             при неуспешно спиране
	 */
	public void unschedule(ServiceWrapper service) throws SchedulerException {
		StdSchedulerFactory.getDefaultScheduler().unscheduleJob(service.getTrigger().getName(),
				service.getDetail().getGroup());
	}

}